package com.sailing.demo.springcloud.apigateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.Filter;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * Created by yunan on 2017/4/22.
 * jwt 验证过滤
 */
public class JWTFilter extends ZuulFilter {

    private static Logger LOGGER = LoggerFactory.getLogger(JWTFilter.class);

    @Value("${jwt.login-path}")
    private String loginPath;

    @Value("${jwt.header}")
    private String jwtHeader;

    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * filterType：返回一个字符串代表本过滤器的类型，在zuul中定义了四种不同生命周期的过滤器类型，具体如下：
     * pre：可以在请求被路由之前调用
     * routing：在路由请求时候被调用
     * post：在routing和error过滤器之后被调用
     * error：处理请求时发生错误时被调用
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 定义过滤器的顺序
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 过滤器开关量 控制过滤器是否执行
     * @return
     */
    @Override
    public boolean shouldFilter() {
        // 获取请求上下文
        RequestContext requestContext = RequestContext.getCurrentContext();
        // 获取请求  HttpServlet 对象
        HttpServletRequest httpServletRequest = requestContext.getRequest();
        // 获取请求路径
        String requestURI = httpServletRequest.getRequestURI();
        if(requestURI.equals(loginPath)){
            LOGGER.info("访问登录接口");
            return false;
        }
        return true;
    }

    /**
     * 过滤器逻辑
     * @return
     */
    @Override
    public Object run() {
        // 获取请求上下文
        RequestContext requestContext = RequestContext.getCurrentContext();
        // 获取请求  HttpServlet 对象
        HttpServletRequest httpServletRequest = requestContext.getRequest();

        LOGGER.info("访问应用接口 {}",httpServletRequest.getRequestURI());
        // 模拟jwt 从头部获取jwt信息
        String jwttoken = httpServletRequest.getHeader(jwtHeader);
        if(null==jwttoken){
            LOGGER.warn("未获取token信息，阻止调用 {}",httpServletRequest.getRequestURI());
            // // 阻止调用
            // requestContext.setSendZuulResponse(false);
            // // 设定返回内容
            // requestContext.setResponseBody("fail to request:no token");
            // // 设定返回state
            // requestContext.setResponseStatusCode(401);
            return null;
        }

        jwttoken = jwttoken.replace(tokenHead,"");

        try {
            Claims claims =Jwts.parser()
                    .setSigningKey(jwtSecret)
                    .parseClaimsJws(jwttoken)
                    .getBody();
            LOGGER.info("来自 {} 的请求 {} 通过网关验证",claims.get("name"),httpServletRequest.getRequestURI());
        } catch (Exception e) {
            LOGGER.error("请求 {} 的token信息异常 {}",httpServletRequest.getRequestURI(),e.getMessage());
            // // 阻止调用
            // requestContext.setSendZuulResponse(false);
            // // 设定返回内容
            // requestContext.setResponseBody(String.format("fail to request:%s",e.getMessage()));
            // // 设定返回state
            // requestContext.setResponseStatusCode(401);
            return null;
        }

        return null;
    }
}
